import json
import time
import traceback
from copy import deepcopy
from datetime import datetime
from functools import partial, wraps
from typing import Dict, List

from mg_app_framework import (HttpBasicHandler, MesCode, TaskKey, get_handler, get_logger,
                              get_organization)

from common.basic_redis import get_redis_conn, build_mg_redis_key


async def filter_web_layout_config() -> Dict:
    """
    获取生产单元管理的基础配置
    """
    redis_handle = get_redis_conn()
    config_key_device_list = build_mg_redis_key(f"web_layout_application_config", app_module_name="web_layout")
    config = await redis_handle.get(config_key_device_list)
    return json.loads(config) if config else {}


async def params_check_call_id(call_id: str, web_layout_config: Dict) -> bool:
    call_id_list = web_layout_config.get("call_id_list", [])
    return call_id in call_id_list


async def params_check_upperpc_code(upperpc_code: str, web_layout_config: Dict) -> bool:
    upperpc_code_list = web_layout_config.get("upperpc_code_list", [])
    return upperpc_code in upperpc_code_list


async def params_check_equip_code(equip_code: str, web_layout_config: Dict) -> bool:
    device_code_list = web_layout_config.get("device_code_list", [])
    return equip_code in device_code_list


async def get_process_code_config():
    redis_handle = get_redis_conn()
    config_key_device_list = build_mg_redis_key(f"production_config_mgm_process_info",
                                                app_module_name="production_config_mgm")
    config = await redis_handle.get(config_key_device_list)
    return json.loads(config) if config else {}


async def params_check_process_code(process_code: str) -> bool:
    process_code_config = await get_process_code_config()
    process_code_list = process_code_config.get("process_code_list", [])
    return process_code in process_code_list


def params_check_decorator(check_params: List[str] = None):
    def wrapper(method):
        @wraps(method)
        async def func(self: HttpBasicHandler, *args, **kwargs):
            request_data: Dict = deepcopy(self.data)
            trace_id = request_data.get("trace_id", None)

            web_lay_out_config = await filter_web_layout_config()
            if not trace_id:
                self._set_response_data({
                    "code": MesCode.fail,
                    "data": None,
                    "info": f"接口接口调用ID为空"
                })
                return
            call_id = request_data.get("call_id", None)
            if not call_id:
                self._set_response_data({
                    "code": MesCode.fail,
                    "data": None,
                    "info": f"接口调用方认证ID为空"
                })
                return
            check_call_id = await params_check_call_id(call_id, web_lay_out_config)
            if not check_call_id:
                self._set_response_data({
                    "code": MesCode.fail,
                    "data": None,
                    "info": f"接口调用方认证ID:{call_id}没有配置"
                })
                return

            if "upperpc_code" in check_params:
                upperpc_code = request_data.get("upperpc_code", None)
                if not upperpc_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"上位机编码为空"
                    })
                    return
                check_upperpc_code = await params_check_upperpc_code(upperpc_code, web_lay_out_config)
                if not check_upperpc_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"上位机编码:{upperpc_code}没有配置"
                    })
                    return
            if "equip_code" in check_params:
                equip_code = request_data.get("equip_code", None)
                if not equip_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"设备编码为空"
                    })
                    return
                check_equip_code = await params_check_equip_code(equip_code, web_lay_out_config)
                if not check_equip_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"设备编码:{equip_code}没有配置"
                    })
                    return

            if "process_code" in check_params:
                process_code = request_data.get("process_code", None)
                if not process_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"工序编码为空"
                    })
                    return
                check_process_code = await params_check_process_code(process_code)
                if not check_process_code:
                    self._set_response_data({
                        "code": MesCode.fail,
                        "data": None,
                        "info": f"工序编码:{process_code}没有配置"
                    })
                    return

            return await method(self, *args, **kwargs)

        return func

    return wrapper
